// Copyright (c) Microsoft Corporation. All rights reserved.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Xml.XPath;

namespace Microsoft.TeamFoundation.Migration.Toolkit.Wit
{
    /// <summary>
    /// Provider-specific target endpoint.
    /// </summary>
    public class OtherMigrationDataSource
    {
        private SystemType m_sourceType;                    // Data source type (TFS/Other)
        private TfsMigrationDataSource m_tfsSource;         // TFS data source (if any)
        private IWorkItemTrackingEndpoint m_otherSource;    // Non-TFS data source (if any)
        

        /// <summary>
        /// Gets the data source type.
        /// </summary>
        public SystemType SourceType { get { return m_sourceType; } }

        /// <summary>
        /// Gets TFS data source, if any
        /// </summary>
        public TfsMigrationDataSource TfsSource { get { return m_tfsSource; } }

        /// <summary>
        /// Gets non-TFS data source, if any
        /// </summary>
        public IWorkItemTrackingEndpoint OtherSource { get { return m_otherSource; } }

        /// <summary>
        /// Returns endpoint regardless of the system type.
        /// </summary>
        public IWorkItemTrackingEndpoint Endpoint
        {
            get
            {
                return m_tfsSource == null ? 
                    (IWorkItemTrackingEndpoint)m_otherSource : (IWorkItemTrackingEndpoint)m_tfsSource;
            }
        }

        /// <summary>
        /// Initializes class from the XML.
        /// </summary>
        /// <param name="nav">XML node</param>
        internal OtherMigrationDataSource(
            XPathNavigator nav,
            WorkItemTrackingSession session)
        {
            Debug.Assert(nav.Name == "Source", "Invalid node!");

            XPathNavigator nav2 = nav.SelectSingleNode("Tfs");
            if (nav2 != null)
            {
                m_sourceType = SystemType.Tfs;
                m_tfsSource = new TfsMigrationDataSource(nav2, session);
            }
            else
            {
                m_sourceType = SystemType.Other;
                nav2 = nav.SelectSingleNode("Provider");
                m_otherSource = GetProviderEndpoint(nav2, session);
            }
        }

        /// <summary>
        /// Creates a work item store object for the given session.
        /// </summary>
        /// <returns>Work item store object</returns>
        internal IMigrationWorkItemStore CreateWorkItemStore()
        {
            return Endpoint.CreateWorkItemStore();
        }

        /// <summary>
        /// Create non-tfs provider.
        /// </summary>
        /// <param name="nav">Xml node</param>
        /// <param name="session">Current session</param>
        /// <returns>Non-Tfs provider</returns>
        private static IWorkItemTrackingEndpoint GetProviderEndpoint(XPathNavigator nav, WorkItemTrackingSession session)
        {
            Debug.Assert(nav.Name == "Provider", "Invalid node!");
            string providerId = nav.GetAttribute("provider", string.Empty);

            //Get write queue config
            QueueConfiguration writeQueueConfig = QueueConfiguration.Create(
               QueueType.Write,
               nav.SelectSingleNode("WriteQueue"));

            //Get custom config info
            nav = nav.SelectSingleNode("InitializationData");
            string initData = string.Empty;
            if (nav != null)
            {
                initData = nav.OuterXml;
            }

            Debug.Assert(MigrationConfiguration.Providers.ContainsKey(providerId));

            MigrationProvider sourceProvider = MigrationConfiguration.Providers[providerId];
            IConfigFactory factory = sourceProvider.CreateFactoryInstance();

            IWorkItemTrackingEndpoint providerEndPoint =
                (IWorkItemTrackingEndpoint)factory.CreateInstance(typeof(IWorkItemTrackingEndpoint), initData);
            if (providerEndPoint == null)
            {
                throw new InitializationException(Resources.EndPointNotFound);
            }
            providerEndPoint.WriteQueueConfig = writeQueueConfig;
            providerEndPoint.Session = session;
            return providerEndPoint;
        }

    }
}
